package com.lwei.ljpro.service.impl;

import com.lwei.ljpro.dto.ExcelData;
import com.lwei.ljpro.entry.UserEntry;
import com.lwei.ljpro.entry.WorkingEntry;
import com.lwei.ljpro.service.IUserService;
import com.lwei.ljpro.service.IWorkingService;
import com.lwei.ljpro.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class WorkingServiceImpl extends BaseServiceImpl<WorkingEntry> implements IWorkingService {

    Logger logger = LoggerFactory.getLogger("WorkingService");

    @Autowired
    private IUserService userService;

    @Override
    protected String getKey() {
        return "WorkingEntry";
    }

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    SimpleDateFormat format_day = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Boolean saveWorkingEntry(WorkingEntry entry, UserEntry userEntry) {
        UserEntry user = userService.checkUserByTel(userEntry.getLoginTel());
        if(user != null){
            entry.setUserId(user.getId());
            Long save = super.save(entry);
            return save != null;
        } else {
            logger.error("保存失败，当前用户为空");
            return false;
        }
    }

    @Override
    public Boolean saveWorkingEntryWithUser(WorkingEntry entry, UserEntry userEntry) {
        Boolean ok = saveWorkingEntry(entry, userEntry);
        if(!ok){
            logger.info("尝试保存,当前用户为空");
            Long id = userService.saveUser(userEntry);
            if(id != null){
                logger.info("创建用户成功，再次尝试保存");
                ok = saveWorkingEntry(entry, userEntry);
            }else{
                logger.info("创建用户失败，不再尝试保存");
            }
        }
        return ok;
    }

    @Override
    public WorkingEntry updateWorkingEntry(WorkingEntry entry) {
        return super.update(entry.getId(), entry);
    }

    @Override
    public WorkingEntry getWorkingEntryById(Long id) {
        return super.getEntryById(id);
    }

    @Override
    public Boolean deleteWorkingEntryById(Long id) {
        return super.delete(id);
    }

    @Override
    public List<WorkingEntry> listWorkingByUser(UserEntry userEntry) {
        List<WorkingEntry> resultList = new ArrayList<>();
        List<WorkingEntry> workingEntryList = this.listWorkingAll();
        if(userEntry.getLoginTel() != null){
            userEntry = userService.checkUserByTel(userEntry.getLoginTel());

        }
        if(userEntry.getId() != null){
            for (WorkingEntry workingEntry : workingEntryList) {
                if(userEntry.getId().equals(workingEntry.getUserId())){
                    resultList.add(workingEntry);
                }
            }
        }

        return resultList;
    }

    @Override
    public List<WorkingEntry> listWorkingByUserToday(UserEntry userEntry) {
        Date planDate = new Date();

        List<WorkingEntry> entryList = listWorkingByUser(userEntry);

        Predicate<WorkingEntry> contain = workingEntry -> DateUtil.getDay(workingEntry.getPlanTime()) == DateUtil.getDay(planDate);
        return entryList.stream().filter(contain).collect(Collectors.toList());

    }

    @Override
    public List<WorkingEntry> listWorkingByUserTomorrow(UserEntry userEntry) {
        Date planDate = new Date();

        List<WorkingEntry> entryList = listWorkingByUser(userEntry);

        Calendar plan = Calendar.getInstance();

        Predicate<WorkingEntry> contain = workingEntry -> DateUtil.getDay(workingEntry.getPlanTime()) > DateUtil.getDay(planDate);
        return entryList.stream().filter(contain).collect(Collectors.toList());

    }

    @Override
    public List<WorkingEntry> listWorkingByPlanTime(String planTimeHorizon, String doneTimeHorizon, Long userId) {

        List<WorkingEntry> workingEntryList = this.listWorkingAll();

        if(userId != null){
            Predicate<WorkingEntry> contain = workingEntry -> workingEntry.getUserId().equals(userId);
            workingEntryList = workingEntryList.stream().filter(contain).collect(Collectors.toList());
        }

        if(StringUtils.isNotBlank(planTimeHorizon)){

            String[] planTime = planTimeHorizon.split("~");
            Date planTimeStat = null;
            Date planTimeEnd = null;
            try {
                planTimeStat = format.parse(planTime[0]);
                planTimeEnd = format.parse(planTime[1]);
            } catch (ParseException e) {
                logger.error("计划日期解析异常", e);
            }

            Date finalPlanTimeStat = planTimeStat;
            Date finalplanTimeEnd = planTimeEnd;
            if(finalPlanTimeStat != null && finalplanTimeEnd != null){
                Predicate<WorkingEntry> statPredicate = workingEntry -> finalPlanTimeStat.before(workingEntry.getPlanTime());
                Predicate<WorkingEntry> endPredicate = workingEntry -> finalplanTimeEnd.after(workingEntry.getPlanTime());
                workingEntryList = workingEntryList.stream().filter(statPredicate.and(endPredicate)).collect(Collectors.toList());
            }
        }

        if(StringUtils.isNotBlank(doneTimeHorizon)){
            String[] doneTime = doneTimeHorizon.split("~");
            Date doneTimeStat = null;
            Date doneTimeEnd = null;
            try {
                doneTimeStat = format.parse(doneTime[0]);
                doneTimeEnd = format.parse(doneTime[1]);
            } catch (ParseException e) {
                logger.error("完成日期解析异常", e);
            }


            Date finalDoneTimeStat = doneTimeStat;
            Date finalDoneTimeEnd = doneTimeEnd;
            if(finalDoneTimeStat != null && finalDoneTimeEnd != null){
                Predicate<WorkingEntry> statPredicate = workingEntry -> finalDoneTimeStat.before(workingEntry.getDoneTime());
                Predicate<WorkingEntry> endPredicate = workingEntry -> finalDoneTimeEnd.after(workingEntry.getDoneTime());
                workingEntryList = workingEntryList.stream().filter(statPredicate.and(endPredicate)).collect(Collectors.toList());
            }
        }

        return workingEntryList;
    }

    @Override
    public List<WorkingEntry> listWorkingAll() {
        return super.listEntryAll(getKey());
    }

    @Override
    public List<WorkingEntry> listWorkingByIds(List<Long> ids) {
        List<WorkingEntry> workingEntryList = this.listWorkingAll();

        List<WorkingEntry> result = new ArrayList<>();
        workingEntryList.forEach(workingEntry -> {
            if(ids.contains(workingEntry.getId())){
                result.add(workingEntry);
            }
        });

        return result;
    }

    @Override
    public List<ExcelData> workingList2ExcelData(List<WorkingEntry> workingList) {
        List<ExcelData> dataList = new ArrayList<>();
        Map<Long, List<WorkingEntry>> listMap = workingList.stream().collect(Collectors.groupingBy(WorkingEntry::getUserId));

        List<String> titles = Arrays.asList("姓名","计划事项","制定时间","是否完成","完成时间","实际情况说明");
        listMap.forEach((userId, workingEntries) ->{
            ExcelData data = new ExcelData();
            List<List<Object>> rows = new ArrayList<>();
            workingEntries.forEach(workingEntry ->{
                List<Object> obj = new ArrayList<>();
                obj.add(workingEntry.getUserName());
                obj.add(workingEntry.getPlan());
                Date planTime = workingEntry.getPlanTime();
                obj.add(planTime == null ? "" : format.format(planTime));
                obj.add(workingEntry.getDone() ? "已完成" : "未完成");
                Date doneTime = workingEntry.getDoneTime();
                obj.add(doneTime == null ? "" : format.format(doneTime));
                obj.add(workingEntry.getContext());
                rows.add(obj);
                data.setName(workingEntry.getUserName());
            });
            data.setRows(rows);
            data.setTitles(titles);
            dataList.add(data);
        });
        return dataList;
    }
}
